#include "MODBUS485_SLAVE.h"

MODBUS485_SLAVE_T* MODBUS485_SLAVE_t;
MODBUS485_SLAVE_List_Par_t MODBUS485_SLAVE_List_Par;

//************************************
// Method:    	MODBUS485_SLAVE_WORK		modbus-485从站工作函数
// Programmer:  lww
// Time:		2019/2/24
// Returns:   	void
//************************************
void CARD_WORK(MODBUS485_SLAVE)()
{
	pthread_t tMODBUS485_SLAVE_RW_ID = 0;

	//< 启动读写线程
	THREAD_CREATE_FAILED(Thread_Create("tMODBUS485_SLAVE_RW_ID", &tMODBUS485_SLAVE_RW_ID, NULL, SCHED_POLICY, 89, true, tMODBUS485_SLAVE_Work_Thread, CONTROL_CORE, NULL));					//< duan 191104 优先级由89变为95
}

//************************************
// Method:    	tMODBUS485_SLAVE_Work_Thread	MODBUS-485从站工作线程
// Programmer:  lww
// Time:		2019/2/25
// Returns:   	void *
// Parameter: 	void * arg
//************************************
void* tMODBUS485_SLAVE_Work_Thread(void* arg)
{
#define MAX_LINK_FAIL_NUM	3
#define MAX_WORK_FAIL_NUM	3
#define PCK_MAXNUM	300
#define STATE	((Port_Chosen == PORT0) ? (Port_State.Port0_State) : (Port_State.Port1_State))
#define OTHER_PORT_STATE	((Port_Chosen == PORT0) ? (Port_State->Port1_State) : (Port_State->Port0_State))
#define FAILED_COUNT	((Port_Chosen == PORT0) ? (Port_State.Port0_Fail_Count) : (Port_State.Port1_Fail_Count))
#define CARD_NUM	(Card_List[TYPE(MODBUS485_SLAVE)].iCount)
#define PORT_STATE_WRITE(name)	{\
	if (Port_Chosen == PORT0)	{ Port_State.Port0_State = name; }\
	if (Port_Chosen == PORT1)	{ Port_State.Port1_State = name; }\
}
#define WRITE_CARD_TIMEOUT_STATE	{\
	for (i = 0; i < CARD_NUM; i++)\
	{\
		base = (NAME(MODBUS485_SLAVE)*)SearchAt(((List_Base_t*)Card_List[TYPE(MODBUS485_SLAVE)].ppData[0]), i);\
		base->Base.Status |= 0x08;		/*卡件超时*/\
	}\
}
#define CANCEL_CARD_TIMEOUT_STATE	{\
	for (i = 0; i < CARD_NUM; i++)\
	{\
		base = (NAME(MODBUS485_SLAVE)*)SearchAt(((List_Base_t*)Card_List[TYPE(MODBUS485_SLAVE)].ppData[0]), i);\
		base->Base.Status &= 0xF7;		/*卡件取消超时*/\
	}\
}
#define WRONG_DEAL	{\
	FAILED_COUNT++;\
	if (FAILED_COUNT >= MAX_LINK_FAIL_NUM)	{\
		close(fd);\
		FAILED_COUNT = MAX_LINK_FAIL_NUM; \
		PORT_STATE_WRITE(UNCONNECT); \
		if (Port_Chosen == PORT0){\
			Port_Chosen = PORT1;\
			Port_Name = PORT1_485;\
		}\
		else\
		{\
			Port_Chosen = PORT0;\
			Port_Name = PORT0_485;\
		}\
	}\
	if ((Port_State.Port0_Fail_Count >= MAX_LINK_FAIL_NUM) && (Port_State.Port1_Fail_Count >= MAX_LINK_FAIL_NUM))	{\
		WRITE_CARD_TIMEOUT_STATE;\
		Port_State.Port0_Fail_Count = 0;\
		Port_State.Port1_Fail_Count = 0;\
	 }\
	continue;\
}
#define MAX_LINK_NUM	20						//< 最大级联的卡件数量

	int fd = -1;
	Port_Chosen_e Port_Chosen;
	const char* Port_Name;
	Port_State_t Port_State;
	unsigned int Band_Rate;						//< 波特率
	unsigned int Data_Bits;						//< 数据位
	char Check_Bit;								//< 校验位
	char Stop_Bit;								//< 停止位
	int i;
	NAME(MODBUS485_SLAVE)* base = NULL;
	char tmp_char;
	unsigned char SendData[PCK_MAXNUM] = { 0 };
	unsigned char RecvData[PCK_MAXNUM] = { 0 };
	short SendCount = 0;
	short RecvCount = 0;
	bool Port_Link_Wrong_Flg = false;			//< 串口连接错误标志
	unsigned short StartAddr;
	unsigned short crc;
	unsigned short NumOfData;
	NAME(MODBUS485_SLAVE)* Card_Pt[MAX_LINK_NUM] = { 0 };	//< 级联的卡件的信息结构体指针数组
	unsigned char Link_Num;									//< 级联的卡件数量
	bool flag = true;										//< 判断卡件级联数量是否正确的标志位
	NAME(MODBUS485_SLAVE)** Base_Pt;
	unsigned short* Pos_Pt;
	NAME(MODBUS485_SLAVE)* Base_Pos = NULL;
	int position = 0;

	printf("the Kernel_%s is %d\r\n", "tMODBUS485_SLAVE_Work_Thread_ID", syscall(SYS_gettid));			//< duan20200610
	//< 初始化参数
	Port_Chosen = PORT0;
	Port_Name = PORT0_485;

	Port_State.Port0_State = UNCONNECT;
	Port_State.Port1_State = UNCONNECT;
	Port_State.Port0_Fail_Count = 0;
	Port_State.Port1_Fail_Count = 0;

	Band_Rate = BandRate_Trans(MODBUS485_SLAVE_List_Par.Band_Rate);
	Data_Bits = DataBits_Trans(MODBUS485_SLAVE_List_Par.Data_Bits);
	Check_Bit = MODBUS485_SLAVE_List_Par.Check_Bit;
	Stop_Bit = MODBUS485_SLAVE_List_Par.Stop_Bit;

	while (1)
	{
		if (SYS_Role != Master_Alone_Role && SYS_Role != Master_Twins_Role)
		{
			if (STATE == UNCONNECT)
			{
				if ((fd = Port_Open(Port_Name, true, O_RDWR | O_NOCTTY, Band_Rate, Data_Bits, Check_Bit, Stop_Bit)) < 0)					
				{
					perror(Port_Name);
					printf("  Open failed\r\n");
					WRONG_DEAL;
				}
				else
				{
					printf(Port_Name);
					printf("  Open success\r\n");
					PORT_STATE_WRITE(BAK);
				}
			}
			if (STATE == BAK)
			{
				ExactDelay(200);
				Clear_Port_Register(fd, CLEAR_IN_AND_OUT);
			}
			continue;
		}

		//< 串口状态为未连接时打开串口
		if (STATE == UNCONNECT)
		{
			//< 参数一：打开串口的设备描述符
			//< 参数二：属性设置，依次为：
			//< 		O_RDWR——读写打开
			//<			O_NOCTTY——如果设备描述符指的是终端设备，则不将此设备分配作为此进程的控制终端(可以告诉Linux这个程序不会成为这个端口上的“控制终端”.如果不这样做的话,所有的输入,比如键盘上过来的Ctrl+C中止信号等等,会影响到你的进程。)
			//<			O_NDELAY——告诉Linux,这个程序并不关心DCD信号线的状态——也就是不关心端口另一端是否已经连接(非阻塞)
			if ((fd = Port_Open(Port_Name, true, O_RDWR | O_NOCTTY , Band_Rate, Data_Bits, Check_Bit, Stop_Bit)) < 0)
			//< Shike20210331 原来是下面这一行： 有| O_NDELAY参数. 因为我们的主站离线，从站切主站后乌沙山现场MODBUS主站串口恢复慢，不阻塞的话会一直重新打开串口，来不及等到MODBUS主站串口恢复，会一直卡在重新打开串口
			//if ((fd = Port_Open(Port_Name, true, O_RDWR | O_NOCTTY | O_NDELAY, Band_Rate, Data_Bits, Check_Bit, Stop_Bit)) < 0)
			{
			//< 打开失败时执行异常处理程序
				perror(Port_Name);
				printf("  Open failed\r\n");
				WRONG_DEAL;
			}
			else
			{
				//< 打开成功时切换状态为备用状态
				printf(Port_Name);
				printf("  Open success\r\n");
				PORT_STATE_WRITE(BAK);
				//< duan 191104 添加 清空串口缓冲区   在测试过程中，OK
				/*ExactDelay(500);
				Clear_Port_Register(fd, CLEAR_IN_AND_OUT);*/
				
			}
		}
		
		//< 串口状态为备份时
		if (STATE == BAK)
		{
			if (Port_Recv(fd, &tmp_char, 1, MODBUS485_SLAVE_List_Par.Recv_Requst_MaxTime, true) < 1)
			{
				continue;
			}
			else
			{
				PORT_STATE_WRITE(WORK);
			}
		}

		//< 串口为工作状态时进行读写操作
		if (STATE == WORK)
		{
			RecvCount = 0;
			SendCount = 0;
			memset(SendData, 0, sizeof(SendData));			//< 初始化接收请求报文数组
			memset(RecvData, 0, sizeof(RecvData));			//< 初始化发送回复报文数组

			while (1)
			{
#define QUIT(name1, name2)	{\
	printf(name1);\
	Port_Link_Wrong_Flg = name2;\
	break;\
}
#define WRONG_CODE2_DEAL	{\
	printf("The address master visit from %d to %d beyond the limit we set in funcode%d\r\n", StartAddr, (StartAddr + NumOfData), RecvData[1]);\
	SendData[1] = (unsigned char)(SendData[1] + 0x80);\
	SendData[SendCount++] = (unsigned char)0x02;\
}
#define WRONG_CODE3_DEAL(name)	{\
	printf(name);\
	printf(" in funcode%d\r\n", RecvData[1]);\
	SendData[1] = (unsigned char)(SendData[1] + 0x80);\
	SendData[SendCount++] = (unsigned char)0x03;\
}
#define ISDOUBLE	(Card_Pt[0]->Sta.Is_Double)
#define CHANNEL_SEARCH_INIT	{\
	Base_Pt = (NAME(MODBUS485_SLAVE) * *)calloc(NumOfData, sizeof(NAME(MODBUS485_SLAVE)*));\
	Pos_Pt = (unsigned short*)calloc(NumOfData, sizeof(unsigned short));\
}

				//< 判断该模件地址下是否存在卡件，根据级联号顺序将该模件地址下存在的卡件的信息结构体指针依次放入指针数组中
				Link_Num = 0;
				memset(Card_Pt, NULL, sizeof(Card_Pt));
				for (i = 0; i < Card_List[TYPE(MODBUS485_SLAVE)].iCount; i++)
				{
					base = (NAME(MODBUS485_SLAVE)*)SearchAt((List_Base_t*)(Card_List[TYPE(MODBUS485_SLAVE)].ppData[0]), i);
					if (base != NULL)
					{
						if (base->Sta.ModuleAddr == tmp_char)
						{
							Card_Pt[base->Sta.Link_No - 1] = base;
							Link_Num++;
						}
					}
				}
				if(Link_Num == 0){ QUIT("The msg don't belong to these module\r\n", false); }	//< 模件地址
				RecvData[RecvCount++] = tmp_char;

				//< 判断级联卡件的数量是否正确
				flag = true;
				for (i = 0; i < Link_Num; i++)
				{
					if (Card_Pt[i] == NULL)
					{
						flag = false;
						break;
					}
				}
				if (flag == false) { QUIT("Unit Number is wrong, please check\r\n", false); }
				
				if (Port_Recv(fd, &tmp_char, 1, MODBUS485_SLAVE_List_Par.Recv_MaxTime, true) < 1) { QUIT("Recv funcode time out\r\n", true); }	//< 功能码
				RecvData[RecvCount++] = tmp_char;
								
				while (Port_Recv(fd, &tmp_char, 1, MODBUS485_SLAVE_List_Par.Recv_MaxTime, true) == 1) { RecvData[RecvCount++] = tmp_char; }		//< 接收剩余信息
				
				crc = (unsigned short)((RecvData[RecvCount - 1] << 8) | RecvData[RecvCount - 2]);							//< 进行crc校验
				if (crc != CRC_Check(RecvData, (RecvCount - 2)))
				{ 
					QUIT("The Request msg can't pass the crc check\r\n", false); 
				}

				//< 组织回复报文
				SendData[SendCount++] = RecvData[0];			//< 模件地址
				SendData[SendCount++] = RecvData[1];			//< 功能码
				StartAddr = (unsigned short)((RecvData[2] << 8) | RecvData[3]);	//< 起始地址

				if (RecvData[1] == 0x01)
				{
					NumOfData = (unsigned short)((RecvData[4] << 8) | RecvData[5]);									//< 访问通道的个数
					CHANNEL_SEARCH_INIT;
					if (NumOfData < 0x0001 || NumOfData > 0x07D0) { WRONG_CODE3_DEAL("The number of channel to visit beyond the limit"); }
					else if (MODBUS485_SLAVE_Channel_Search(Card_Pt, Base_Pt, Pos_Pt, DI_CHA, StartAddr, NumOfData, ISDOUBLE, Link_Num) == false) { WRONG_CODE2_DEAL; }
					else
					{
						SendData[SendCount++] = (unsigned char)(NumOfData / 8 + (((NumOfData % 8) == 0) ? 0 : 1));		//< 返回的字节数
						for (i = 0; i < NumOfData; i++)
						{
							SendData[SendCount + i / 8] = (unsigned char)(SendData[SendCount + i / 8] | (Base_Pt[i]->Base.DIChannel[Pos_Pt[i]].Sta_Property.CurOut_Value << (i % 8)));
						}
						SendCount = (short)(SendCount + SendData[2]);
					}
				}
				else if (RecvData[1] == 0x02)
				{
					NumOfData = (unsigned short)((RecvData[4] << 8) | RecvData[5]);									//< 访问通道的个数
					CHANNEL_SEARCH_INIT;
					if (NumOfData < 0x0001 || NumOfData > 0x07D0) { WRONG_CODE3_DEAL("The number of channel to visit beyond the limit"); }
					else if (MODBUS485_SLAVE_Channel_Search(Card_Pt, Base_Pt, Pos_Pt, DO_CHA, StartAddr, NumOfData, ISDOUBLE, Link_Num) == false) { WRONG_CODE2_DEAL; }
					else
					{
						SendData[SendCount++] = (unsigned char)(NumOfData / 8 + (((NumOfData % 8) == 0) ? 0 : 1));		//< 返回的字节数
						for (i = 0; i < NumOfData; i++)
						{
							SendData[SendCount + i / 8] = (unsigned char)(SendData[SendCount + i / 8] | (Base_Pt[i]->Base.DOChannel[Pos_Pt[i]].Sta_Property.CurOut_Value << (i % 8)));
						}
						SendCount = (short)(SendCount + SendData[2]);
					}
				}
				else if (RecvData[1] == 0x03)
				{
					NumOfData = (unsigned short)((RecvData[4] << 8) | RecvData[5]);									//< 访问通道的个数
					CHANNEL_SEARCH_INIT;
					if (NumOfData < 0x0001 || NumOfData > 0x007D) { WRONG_CODE3_DEAL("The number of channel to visit beyond the limit"); }
					else if (MODBUS485_SLAVE_Channel_Search(Card_Pt, Base_Pt, Pos_Pt, AI_CHA, StartAddr, NumOfData, ISDOUBLE, Link_Num) == false) { WRONG_CODE2_DEAL; }
					else
					{
						SendData[SendCount++] = (unsigned char)(2 * NumOfData);
						if (ISDOUBLE == true)
							for (i = 0; i < NumOfData; i++)
							{
								int tmp_int;
								tmp_int = *((int*) & (Base_Pt[i]->Base.AIChannel[Pos_Pt[i]].Sta_Property.CurOut_Value));
								if (((StartAddr + i- Base_Pt[i]->Par.StartAddrOf_AI) % 2) == 0)//< 决定取float的前两个字节还是后两个字节
								{
									SendData[SendCount + 2 * i + 0] = (unsigned char)((tmp_int >> 24) & 0xFF);
									SendData[SendCount + 2 * i + 1] = (unsigned char)((tmp_int >> 16) & 0xFF);
								}
								else
								{
									SendData[SendCount + 2 * i + 0] = (unsigned char)((tmp_int >> 8) & 0xFF);
									SendData[SendCount + 2 * i + 1] = (unsigned char)(tmp_int & 0xFF);
								}								
							}
						else
							for (i = 0; i < NumOfData; i++)
							{
								unsigned short tmp_ushort;
								tmp_ushort = (unsigned short)Base_Pt[i]->Base.AIChannel[Pos_Pt[i]].Sta_Property.CurOut_Value;
								SendData[SendCount + 2 * i + 0] = (unsigned char)((tmp_ushort >> 8) & 0xFF);
								SendData[SendCount + 2 * i + 1] = (unsigned char)(tmp_ushort & 0xFF);
							}
						SendCount = (short)(SendCount + SendData[2]);
					}
				}
				else if (RecvData[1] == 0x04)
				{
					NumOfData = (unsigned short)((RecvData[4] << 8) | RecvData[5]);									//< 访问通道的个数
					CHANNEL_SEARCH_INIT;
					if (NumOfData < 0x0001 || NumOfData > 0x007D) { WRONG_CODE3_DEAL("The number of channel to visit beyond the limit"); }
					else if (MODBUS485_SLAVE_Channel_Search(Card_Pt, Base_Pt, Pos_Pt, AO_CHA, StartAddr, NumOfData, ISDOUBLE, Link_Num) == false) { WRONG_CODE2_DEAL; }
					else
					{
						SendData[SendCount++] = (unsigned char)(2 * NumOfData);
						if (ISDOUBLE == true)
							for (i = 0; i < NumOfData; i++)
							{
								int tmp_int;
								tmp_int = *((int*) & (Base_Pt[i]->Base.AOChannel[Pos_Pt[i]].Sta_Property.CurOut_Value));
								if (((StartAddr + i - Base_Pt[i]->Par.StartAddrOf_AO) % 2) == 0)//< 决定取float的前两个字节还是后两个字节
								{
									SendData[SendCount + 2 * i + 0] = (unsigned char)((tmp_int >> 24) & 0xFF);
									SendData[SendCount + 2 * i + 1] = (unsigned char)((tmp_int >> 16) & 0xFF);
								}
								else
								{
									SendData[SendCount + 2 * i + 0] = (unsigned char)((tmp_int >> 8) & 0xFF);
									SendData[SendCount + 2 * i + 1] = (unsigned char)(tmp_int & 0xFF);
								}
							}
						else
							for (i = 0; i < NumOfData; i++)
							{
								unsigned short tmp_ushort;
								tmp_ushort = (unsigned short)Base_Pt[i]->Base.AOChannel[Pos_Pt[i]].Sta_Property.CurOut_Value;
								SendData[SendCount + 2 * i] = (unsigned char)((tmp_ushort >> 8) & 0xFF);
								SendData[SendCount + 2 * i + 1] = (unsigned char)(tmp_ushort & 0xFF);
							}
						SendCount = (short)(SendCount + SendData[2]);
					}
				}
				else if (RecvData[1] == 0x05)
				{
					unsigned short tmp_ushort;
					tmp_ushort = (unsigned short)((RecvData[4] << 8) | RecvData[5]);
					NumOfData = 1;
					CHANNEL_SEARCH_INIT;
					if (tmp_ushort != 0x0000 && tmp_ushort != 0xFF00) { WRONG_CODE3_DEAL("The value of channel is not equal to 0x0000 or 0xFF00"); }
					else if (MODBUS485_SLAVE_Channel_Search(Card_Pt, Base_Pt, Pos_Pt, DI_CHA, StartAddr, NumOfData, ISDOUBLE, Link_Num) == false) { WRONG_CODE2_DEAL; }
					else
					{
						SendData[SendCount++] = RecvData[2];
						SendData[SendCount++] = RecvData[3];
						SendData[SendCount++] = RecvData[4];
						SendData[SendCount++] = RecvData[5];
						if (tmp_ushort == 0x0000)
							DV_Write(&(Base_Pt[0]->Base.DIChannel[Pos_Pt[0]]), false, WRITE);
						else if (tmp_ushort == 0xFF00)
							DV_Write(&(Base_Pt[0]->Base.DIChannel[Pos_Pt[0]]), true, WRITE);
					}
				}
				else if (RecvData[1] == 0x06)
				{
				/*unsigned short tmp_ushort;		
				tmp_ushort = (unsigned short)((RecvData[4] << 8) | RecvData[5]);*/		//< duan 191030注释 只能是正数
					short tmp_ushort;													//< duan 191030修改
					tmp_ushort = (short)((RecvData[4] << 8) | RecvData[5]);
					NumOfData = 1;
					CHANNEL_SEARCH_INIT;
					/*if (tmp_ushort < 0x0000 || tmp_ushort > 0xFFFF) { WRONG_CODE3_DEAL("The value of channel is not vary from 0x0000 to 0xFFFF"); }*/			//< duan 191030注释
					if (tmp_ushort < (short)0x8001 || tmp_ushort > (short)0x7FFF) { WRONG_CODE3_DEAL("The value of channel is not vary from -32767 to 32767");}		//< duan 191030修改
					else if (MODBUS485_SLAVE_Channel_Search(Card_Pt, Base_Pt, Pos_Pt, AI_CHA, StartAddr, NumOfData, ISDOUBLE, Link_Num) == false) { WRONG_CODE2_DEAL; }
					else
					{
						SendData[SendCount++] = RecvData[2];
						SendData[SendCount++] = RecvData[3];
						SendData[SendCount++] = RecvData[4];
						SendData[SendCount++] = RecvData[5];
						AV_Write(&(Base_Pt[0]->Base.AIChannel[Pos_Pt[0]]), (float)tmp_ushort, WRITE);
					}
				}
				else if (RecvData[1] == 0x0F)
				{
					NumOfData = (unsigned short)((RecvData[4] << 8) | RecvData[5]);
					CHANNEL_SEARCH_INIT;
					if (NumOfData < 0x0001 || NumOfData > 0x07B0) { WRONG_CODE3_DEAL("The number of channel to visit beyond the limit"); }
					else if (MODBUS485_SLAVE_Channel_Search(Card_Pt, Base_Pt, Pos_Pt, DI_CHA, StartAddr, NumOfData, ISDOUBLE, Link_Num) == false) { WRONG_CODE2_DEAL; }
					else
					{
						SendData[SendCount++] = RecvData[2];
						SendData[SendCount++] = RecvData[3];
						SendData[SendCount++] = RecvData[4];
						SendData[SendCount++] = RecvData[5];
						for (i = 0; i < NumOfData; i++)
						{
							DV_Write(&(Base_Pt[i]->Base.DIChannel[Pos_Pt[i]]), (RecvData[7 + i / 8] & (0x01 << (i % 8))), WRITE);
						}
					}
				}
				else if (RecvData[1] == 0x10)
				{
					unsigned char Float_Byte[4];
					NumOfData = (unsigned short)((RecvData[4] << 8) | RecvData[5]);
					CHANNEL_SEARCH_INIT;
					if (NumOfData < 0x0001 || NumOfData > 0x007B) { WRONG_CODE3_DEAL("The number of channel to visit beyond the limit"); }
					else if (MODBUS485_SLAVE_Channel_Search(Card_Pt, Base_Pt, Pos_Pt, AI_CHA, StartAddr, NumOfData, ISDOUBLE, Link_Num) == false) { WRONG_CODE2_DEAL; }
					else
					{
						SendData[SendCount++] = RecvData[2];
						SendData[SendCount++] = RecvData[3];
						SendData[SendCount++] = RecvData[4];
						SendData[SendCount++] = RecvData[5];
						i = 0;
						if (ISDOUBLE == true)
							while(i < NumOfData)
							{
								int tmp_int;
								Base_Pos = Base_Pt[i];
								position = Pos_Pt[i];
								tmp_int = *((int*) & (Base_Pos->Base.AIChannel[position].Sta_Property.CurOut_Value));
								Float_Byte[0] = (unsigned char)((tmp_int >> 24) & 0xFF);
								Float_Byte[1] = (unsigned char)((tmp_int >> 16) & 0xFF);
								Float_Byte[2] = (unsigned char)((tmp_int >> 8) & 0xFF);
								Float_Byte[3] = (unsigned char)((tmp_int >> 0) & 0xFF);

								if (((StartAddr + i - Base_Pos->Par.StartAddrOf_AI) % 2) == 0)//< 决定取float的前两个字节还是后两个字节
								{
									Float_Byte[0] = RecvData[7 + 2 * i + 0];
									Float_Byte[1] = RecvData[7 + 2 * i + 1];
									i++;
									if (i < NumOfData)
									{
										Float_Byte[2] = RecvData[7 + 2 * i + 0];
										Float_Byte[3] = RecvData[7 + 2 * i + 1];
										i++;
									}
								}
								else
								{
									Float_Byte[2] = RecvData[7 + 2 * i + 0];
									Float_Byte[3] = RecvData[7 + 2 * i + 1];
									i++;
								}

								tmp_int = (Float_Byte[0] << 24 | Float_Byte[1] << 16 | Float_Byte[2] << 8 | Float_Byte[3]);
								AV_Write(&(Base_Pos->Base.AIChannel[position]), *((float*)&tmp_int), WRITE);
								
							}
						else
							for (i = 0; i < NumOfData; i++)
							{
								/*AV_Write(&(Base_Pt[i]->Base.AIChannel[Pos_Pt[i]]), (float)(RecvData[7 + 2 * i] << 8 | RecvData[7 + 2 * i + 1]), WRITE);*/				//< duan 191030 注释 只能接收 unsigned int
								AV_Write(&(Base_Pt[i]->Base.AIChannel[Pos_Pt[i]]), (float)((short)(RecvData[7 + 2 * i] << 8 | RecvData[7 + 2 * i + 1])), WRITE);		//< duan 191030
							}
					}
				}
				else
				{
					printf("The msg's funcode is wrong\r\n");
					SendData[1] = (unsigned char)(SendData[1] + 0x80);
					SendData[SendCount++] = 0x01;
				}

				FREE_Pt(Base_Pt);
				FREE_Pt(Pos_Pt);
				crc = CRC_Check(SendData, SendCount);
				SendData[SendCount++] = (unsigned char)(crc & 0x00FF);
				SendData[SendCount++] = (unsigned char)(crc >> 8);
				if (Port_Send(fd, SendData, SendCount, MODBUS485_SLAVE_List_Par.Send_MaxTime, true) < SendCount) { QUIT("Send response msg wrong\n", true); }
				QUIT(NULL, false);
				
#undef QUIT
#undef WRONG_CODE2_DEAL
#undef WRONG_CODE3_DEAL
#undef ISDOUBLE
#undef CHANNEL_SEARCH_INIT
			}
			if (Port_Link_Wrong_Flg == false)
			{
				int bytes = 0;
				FAILED_COUNT = 0;
				CANCEL_CARD_TIMEOUT_STATE;
				do 
				{
					ioctl(fd, TIOCOUTQ, &bytes);//< 确保发送缓存区数据发送完毕后再切换串口至备用模式
				} while (bytes > 0);
				PORT_STATE_WRITE(BAK);
			}
			else
			{
				ExactDelay(200);
				Clear_Port_Register(fd, CLEAR_IN_AND_OUT);
				WRONG_DEAL;
			}
		}
	}
#undef MAX_LINK_FAIL_NUM
#undef MAX_WORK_FAIL_NUM
#undef PCK_MAXNUM
#undef STATE
#undef OTHER_PORT_STATE
#undef FAILED_COUNT
#undef CARD_NUM
#undef PORT_STATE_WRITE
#undef WRITE_CARD_TIMEOUT_STATE
#undef CANCEL_CARD_TIMEOUT_STATE
#undef WRONG_DEAL
#undef MAX_LINK_NUM
	return NULL;
}

//************************************
// Method:    	MODBUS485_SLAVE_Channel_Search		寻找主站访问的地址是否越界
// Programmer:  lww
// Time:		2019/9/16
// Returns:   	bool								true-成功；false-失败
// Parameter: 	NAME(MODBUS485_SLAVE)* Card_Pt[]	级联的卡件信息结构体数组
// Parameter: 	Channel_type_e type					通道类型
// Parameter: 	unsigned short StartAddr			起始地址
// Parameter: 	unsigned short NumOfData			通道数量
// Parameter: 	bool Is_Double						是否为双字
// Parameter: 	unsigned char Link_Num				级联的卡件的数量
//************************************
bool MODBUS485_SLAVE_Channel_Search(NAME(MODBUS485_SLAVE)* Card_Pt[], NAME(MODBUS485_SLAVE)** Base_Pt, unsigned short* Pos_Pt, Channel_type_e type, unsigned short StartAddr, unsigned short NumOfData, bool Is_Double, unsigned char Link_Num)
{
	int i, j;
	bool Exist_Flag = false;
	for (i = StartAddr; i < StartAddr + NumOfData; i++)
	{
		Exist_Flag = false;
		for (j = 0; j < Link_Num; j++)
		{
			if (type == DI_CHA && ((i >= Card_Pt[j]->Par.StartAddrOf_DI) && (i < Card_Pt[j]->Par.StartAddrOf_DI + Card_Pt[j]->Base.IO_Num.DI_Num)))
			{
				Pos_Pt[i - StartAddr] = i - Card_Pt[j]->Par.StartAddrOf_DI;			//< duan 0917记录主站访问的数据通道在该张卡件通道的位置
				Exist_Flag = true;
			}

			if (type == DO_CHA && ((i >= Card_Pt[j]->Par.StartAddrOf_DO) && (i < Card_Pt[j]->Par.StartAddrOf_DO + Card_Pt[j]->Base.IO_Num.DO_Num)))
			{
				Pos_Pt[i - StartAddr] = i - Card_Pt[j]->Par.StartAddrOf_DO;
				Exist_Flag = true;
			}

			if (type == AI_CHA && ((i >= Card_Pt[j]->Par.StartAddrOf_AI) && (i < Card_Pt[j]->Par.StartAddrOf_AI + (Card_Pt[j]->Base.IO_Num.AI_Num * ((Is_Double == true) ? 2 : 1)))))
			{
				Pos_Pt[i - StartAddr] = (i - Card_Pt[j]->Par.StartAddrOf_AI) / ((Is_Double == true) ? 2 : 1);
				Exist_Flag = true;
			}

			if (type == AO_CHA && ((i >= Card_Pt[j]->Par.StartAddrOf_AO) && (i < Card_Pt[j]->Par.StartAddrOf_AO + (Card_Pt[j]->Base.IO_Num.AO_Num * ((Is_Double == true) ? 2 : 1)))))
			{
				Pos_Pt[i - StartAddr] = (i - Card_Pt[j]->Par.StartAddrOf_AO) / ((Is_Double == true) ? 2 : 1);
				Exist_Flag = true;
			}

			if (Exist_Flag == true)
			{
				Base_Pt[i - StartAddr] = Card_Pt[j];			//< duan0917 记录主站访问的每一个数据通道所在卡件的位置
				break;
			}
		}
		if (Exist_Flag == false)
			return false;
	}
	return true;
}

//************************************
// Method:    	CHANGE_CARD_LIST_PAR		修改该类型卡件属性
// Programmer:  lww
// Time:		2019/4/4
// Returns:   	int							读取字节长度计数值
// Parameter: 	Card_Base_t* arg			指定卡件属性结构体的指针
// Parameter: 	void** Data					存放数据包当前指针位置的地址
//************************************
int CHANGE_CARD_LIST_PAR(MODBUS485_SLAVE)(Card_Base_t* arg, void** Data)
{
	int _iLen = 0;
	MEMREAD((*CLIST_PAR(MODBUS485_SLAVE)), Data[0]);
	return _iLen;
}


//************************************
// Method:    	CHANGE_CARD_PAR				在线修改卡件参数函数
// Programmer:  lww
// Time:		2018/11/16
// Returns:   	int							读取字节长度计数值
// Parameter: 	Card_Base_t* arg			指定卡件属性结构体的指针
// Parameter: 	void** Data					存放数据包当前指针位置的地址
//************************************
int CHANGE_CARD_PAR(MODBUS485_SLAVE)(Card_Base_t* arg, void** Data)
{
	int _iLen = 0;
	MEMREAD(((NAME(MODBUS485_SLAVE)*)arg)->Par, Data[0]);
	return _iLen;
}
//************************************
// Method:    	INIT_STAPAR					初始化卡件不可调参数结构体
// Programmer:  lww
// Time:		2018/11/16
// Returns:   	int							读取字节长度计数值
// Parameter: 	Card_Base_t* arg			指定卡件属性结构体的指针
// Parameter: 	void** Data					存放数据包当前指针位置的地址
//************************************
int INIT_CARD_STA(MODBUS485_SLAVE)(Card_Base_t* arg, void** Data)
{
	int _iLen = 0;
	MEMREAD(((NAME(MODBUS485_SLAVE)*)arg)->Sta, Data[0]);
	return _iLen;
}
